import os
from rpyc.utils.security.base import BaseDB, ProtocolError, ProtocolAuthError 

try:
    #
    # python 2.6 and above
    #
    from ssl import wrap_socket as wrap_ssl
    from ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv23, PROTOCOL_SSLv3, PROTOCOL_TLSv1
    from ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED 
    DEFAULT_PROTOCOL = PROTOCOL_TLSv1

except ImportError:
    #
    # python 2.5 and below
    #
    PROTOCOL_SSLv2 = -1000
    PROTOCOL_SSLv23 = 0
    PROTOCOL_SSLv3 = -1000
    PROTOCOL_TLSv1 = -1000
    CERT_NONE = 0
    CERT_OPTIONAL = -1000
    CERT_REQUIRED = -1000
    DEFAULT_PROTOCOL = PROTOCOL_SSLv23
    
    try:
        from socket import ssl as _wrap_ssl
        
        def wrap_ssl(sock, keyfile = None, certfile = None, server_side = False, 
                ssl_version = None, cert_reqs = None, ca_certs = None):
            if ssl_version not in (PROTOCOL_SSLv2, PROTOCOL_SSLv23, PROTOCOL_SSLv3):
                raise ValueError("unsupported ssl version")
            if ca_certs or cert_reqs != CERT_NONE:
                raise ValueError("validating certificates against CA not supported")
            if keyfile is None and certfile:
                keyfile = certfile
            return _wrap_ssl(sock, keyfile, certfile)

    except ImportError:
        #
        # very old python or no ssl support compiled
        #
        def wrap_ssl(*args, **kwargs):
            raise NotImplementedError("ssl support unavailable")


class TlsProtocol(object):
    GENERIC_CERTFILE = os.path.join(os.path.dirname(__file__), "generic-cert.pem")
    
    @classmethod
    def handshake_server(cls, sock, certfile = GENERIC_CERTFILE, cafile = None, version = DEFAULT_PROTOCOL):
        if cafile:
            cert_reqs = CERT_REQUIRED
        else:
            cert_reqs = CERT_NONE
        return wrap_ssl(sock, server_side = True, certfile = certfile, 
            ssl_version = version, cert_reqs = cert_reqs, ca_certs = cafile)
    
    @classmethod
    def handshake_client(cls, sock, certfile = None, cafile = None, version = DEFAULT_PROTOCOL):
        if cafile:
            cert_reqs = CERT_REQUIRED
        else:
            cert_reqs = CERT_NONE
        return wrap_ssl(sock, server_side = False, certfile = certfile, 
            ssl_version = version, cert_reqs = cert_reqs, ca_certs = cafile)


